#include "parser.hh"

#include <iostream>
#include <cctype>

static bool is_numeric(std::string& s)
{
  int i = 0;
  while ((i < s.length()) && isdigit((int) s[i]))
    {
      i++;
    }

  return (i == s.length());
}

void t_stage::parse(std::istream& in,
		    t_variables_map& variables,
		    t_input_vars_map& input_variables,
		    t_output_vars_map& output_variables)
{
  std::string useless;

  in >> ret;

  if (ret.compare("output") == 0)
    {
      operation = "output";
      ret = "";
    }
  else
    {
      in >> useless;
      in >> operation;
    }

  while (in.good())
    {
      std::string arg;
      in >> arg;
      args.push_back(arg);

      if (!is_operation(arg) && !is_numeric(arg))
	{ // argument type is variable

	  { // check whether the variable is a necessary input
	    if (variables.find(arg) == variables.end())
	      {
		input_variables[arg] = NULL;
	      }
	  }

	  { // check whether the variable is an output one
	    if (operation.compare("output") == 0)
	      {
		output_variables[arg] = NULL;
	      }
	  }

	  { // Add the variable to the variables map
	    variables[arg] = NULL;
	  }
	}
    }

  { // Add the ret variable to the variables map
    if (ret.length() > 0)
      variables[ret] = NULL;
  }
}

std::string t_stage::to_string() const
{
  std::string result;

  if (operation.compare("output") != 0)
    {
      result += ret + " = ";
    }

  result += operation + "( ";

  
  for (std::vector<std::string>::const_iterator it = args.begin();
       it != args.end(); ++it)
    {
      result += *it + " ";
    }

  result += ")";

  return result;
}

void t_toolchain::parse(std::istream& in)
{
  while (in.good())
    {
      std::string line;
      getline(in, line);

      if (line.compare("") == 0)
	continue;

      std::istringstream iss(line);

      t_stage stage;
      stage.parse(iss, variables, input_variables, output_variables);

      if (stage.operation.compare("output") != 0)
	stages.push_back(stage);
    }
}

std::string t_toolchain::to_string() const
{
  std::string result;

  result += "Input variables:";
  
  for (t_input_vars_map::const_iterator it = input_variables.begin();
       it != input_variables.end(); ++it)
    {
      result += " " + it->first;
    }

  result += '\n';

  for (std::list<t_stage>::const_iterator it = stages.begin();
       it != stages.end(); ++it)
    {
      result += it->to_string() + '\n';
    }

  result += "Output variables:";

  for (t_output_vars_map::const_iterator it = output_variables.begin();
       it != output_variables.end(); ++it)
    {
      result += " " + it->first;
    }

  result += '\n';

  return result;
}
